package com.apes.fn.scm.appScan;

import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.apes.fn.scm.retailOrder.model.RetailOrder;
import com.apes.fn.scm.retailReturn.RetailReturn;
import com.apes.framework.api.SpringManager;
import com.apes.framework.jpa.logger.ApesLoggerService;
import com.apes.framework.jpa.spec.JpaDsl;
import com.apes.framework.plugin.esb.api.SimpleRequest;
import com.apes.framework.util.EventUtil;
import com.apes.framework.util.MapUtil;
import com.apes.scm.pur.purchaseOrder.model.PurchaseOrder;
import com.apes.scm.pur.purchaseReturn.model.PurchaseReturn;
import com.apes.scm.rbac.model.User;
import com.apes.scm.rbac.repository.UserRepository;
import com.apes.scm.sal.saleOrder.SaleOrder;
import com.apes.scm.sal.saleReturn.SaleReturn;
import com.apes.scm.stock.transfer.model.Pick;
import com.apes.scm.stock.transfer.model.Transfer;
import com.apes.scm.stock.transfer.repository.PickRepository;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import java.util.*;
import java.util.stream.Collectors;


@Component
public class PickTemplate extends SimpleTemplate {

    private enum Orders {

        // 查询接口参数使用, 其他为查询结果或者提交接口参数使用
        Pick("pick", "交货单"),

        Purchase(PurchaseOrder.class.getSimpleName(), "采购订单"),
        PurchaseRe(PurchaseReturn.class.getSimpleName(), "返厂订单"),
        Retail(RetailOrder.class.getSimpleName(), "零售订单"),
        RetailRe(RetailReturn.class.getSimpleName(), "零售退货订单"),
        Sale(SaleOrder.class.getSimpleName(), "分销订单"),
        SaleRe(SaleReturn.class.getSimpleName(), "分销退货订单"),
        Transfer(Transfer.class.getSimpleName(), "转储订单");

        private String type;
        private String name;

        Orders(String type, String name) {
            this.type = type;
            this.name = name;
        }

        public static String getName(String type) {
            String name = null;
            for (Orders orders : values()) {
                if (type.equals(orders.type)) {
                    name = orders.name;
                }
            }
            return name;
        }

        public static String[] getTypes() {
            int len = values().length;
            String[] types = new String[len];
            for (int i = 0; i < len; i++) {
                types[i] = values()[i].type;
            }
            return types;
        }
    }

    @Autowired
    PickRepository pickRepository;

    @Override
    public String[] identifys() {
        return Orders.getTypes();
    }

    @Override
    public JSONObject getOrder(String id) {
        Pick pick = getPick(id);
        JSONObject result = mapperPick(pick);
        result.put("CZFS", pick.getOperation().equals("deliver") ? 0 : 1);
        result.put("YXBFSMBJ", pick.getMoveType().getCode().equals("one") ? 0 : 1);
        result.put("YXSYSLBJ", 1);
        result.put("DJZT", pick.getState());

        if (Objects.isNull(pick.getAppScanPerson())) {
            result.put("SMR", "");
        } else {
            result.put("SMR", SpringManager.getBean(UserRepository.class).findByOrigin(pick.getAppScanPerson()).getName());
        }

        result.put("WAR_TMCRKDMX", pick.getPickItems().stream().map(
                (item) -> {
                    JSONObject itemO = new JSONObject();
                    itemO.put("XH", item.getId());
                    itemO.put("LYXH", item.getId());
                    itemO.put("HSBL", 1);
                    itemO.put("SPID", item.getProduct().getId());
                    itemO.put("SPMC", item.getProduct().getName());
                    itemO.put("JLDW", item.getUom().getName());
                    itemO.put("CRKDH", result.getString("CRKDH"));
                    itemO.put("DJSL", item.getProductUomQty());
                    itemO.put("DJJS", item.getProductUomQty());
                    itemO.put("SMJS", 0);
                    itemO.put("SMSL", 0);
                    itemO.put("GYSTM", item.getProduct().getBarcode());
                    return itemO;
                }
        ).collect(Collectors.toCollection(JSONArray::new)));
        return result;
    }

    @Override
    public JSONArray getOrderLists(SimpleRequest request, String origin) {
        List<String> deptIds = getOperatorDept(request);
        List<String> locationIds = getOperatorLocation(request);
        List<Pick> picks = pickRepository.findPicksForPDA(origin, deptIds, locationIds);
        return picks.stream().map(this::mapperPick).collect(Collectors.toCollection(JSONArray::new));
    }

    private JSONObject mapperPick(Pick pick) {
        JSONObject result = new JSONObject();
        result.put("CRKDH", pick.getId());
        result.put("DJLXID", pick.getInnerBusinessType());
        result.put("DJLXMC", Orders.getName(pick.getInnerBusinessType()));
        result.put("LYDJLX", "pick");
        result.put("LYDJMC", Orders.getName(result.getString("LYDJLX")));
        result.put("LYDJHM", pick.getOrigin());
        result.put("XSMC", result.getString("LYDJMC"));
        result.put("CZMC", result.getString("LYDJMC"));
        result.put("CKKQID", pick.getLocation().getId());
        result.put("CKKQMC", pick.getLocation().getName());
        result.put("CKID", pick.getLocation().getDepot().getId());
        result.put("CKMC", pick.getLocation().getDepot().getName());
        result.put("DFID", pick.getPartner().getId());
        result.put("DFMC", pick.getPartner().getName());
        result.put("DJZT", pick.getState());
        if (Objects.isNull(pick.getAppScanPerson())) {
            result.put("SMR", "");
        } else {
            result.put("SMR", SpringManager.getBean(UserRepository.class).findByOrigin(pick.getAppScanPerson()).getName());
        }
        return result;
    }

    @Override
    public void begin(String id, String userId) {
        setPickLocked(id, userId, true);
    }

    @Override
    public void cancel(String id, String userId) {
        setPickLocked(id, userId, false);
    }

    @Override
    public void submit(SimpleRequest request) {
        String id = request.get("CRKDH");
        // 先解锁
        Pick pick = setPickLocked(id, request.getPersonId(), false);
        // 不对bean操作,不然会刷新对象值
        Map pickJO = MapUtil.mapped(pick);
        Map<Long, JSONObject> pickMap = new JSONObject(pickJO).getJSONArray("pickItems").stream()
                .collect(Collectors.toMap(
                        x -> {
                            if (x instanceof HashMap) {
                                Map m = (HashMap) x;
                                JSONObject jsonObject = new JSONObject(m);
                                return jsonObject.getLong("id");
                            } else {
                                return ((JSONObject) x).getLong("id");
                            }
                        },
                        item -> {
                            if (item instanceof HashMap) {
                                Map m = (HashMap) item;
                                return new JSONObject(m);
                            } else {
                                return (JSONObject) item;
                            }
                        })
                );
        pickJO.put("pickItems", ((JSONArray) request.get("WAR_TMCRKDMX")).stream().map(
                item -> {
                    JSONObject itemO = (JSONObject) item;
                    Long index = itemO.getLong("XH");
                    if (pickMap.containsKey(index)) {
                        JSONObject pickItem = pickMap.get(index);
                        if (pickItem.getJSONObject("product").getString("id").equals(itemO.getString("SPID"))) {
                            pickItem.put("qtyDone", itemO.getDouble("SMJS"));
                            return pickItem;
                        } else {
                            throw new RuntimeException("明细编码与商品编码对应关系不一致！");
                        }
                    } else {
                        throw new RuntimeException("明细编码不存在！");
                    }
                }
        ).collect(Collectors.toCollection(JSONArray::new)));
        EventUtil.sendSynEvent(this, "event:stock.pick.pda", pickJO);   // 保存

        // 记录日志
        List<User> userInfo = SpringManager.getBean(UserRepository.class).findAll(JpaDsl.toCriteriaByEq("person.id", pick.getAppScanPerson()));
        SpringManager.getBean(ApesLoggerService.class).sendSynEvent("event:ir.logger.create", MapUtil.mapper(
                "businessType", pick.getInnerBusinessType(),
                "businessKey", pick.getInnerBusinessKey(),
                "operate","扫描端提交" ,
                "workPostName", null,
                "audit", null,
                "operator_id", userInfo.get(0).getId().toString()));
    }

    private Pick getPick(String id) {
        Pick pick = pickRepository.findOne(id);
        Optional.ofNullable(pick).orElseThrow(() -> new RuntimeException("未找到有效的交货单！"));
        if ("done".equals(pick.getState())) throw new RuntimeException(String.format("交货单[%s]已完成！禁止操作！", pick.getId()));
        return pick;
    }

    private Pick save(Pick pick) {
        return pickRepository.saveAndFlush(pick);
    }

    private Pick setPickLocked(String id, String userId, boolean locked) {
        Pick pick = getPick(id);
        if (locked) {
            if ("locked".equals(pick.getState())) throw new RuntimeException("该单据已锁定，不允许操作！请解锁，点取消扫码即可");
            pick.setState("locked");
            pick.setAppScanDate(new Date());
            pick.setAppScanPerson(userId);
        } else {
            if ("confirmed".equals(pick.getState())) throw new RuntimeException("取消成功，请继续扫码！");
            if (!userId.equals(pick.getAppScanPerson()))
                throw new RuntimeException(String.format("单号已锁定！请联系 %s 重新操作单据", SpringManager.getBean(UserRepository.class).findByOrigin(pick.getAppScanPerson()).getName()));
            pick.setState("confirmed");
            pick.setAppScanDate(new Date());
            pick.setAppScanPerson(userId);
        }
        return save(pick);
    }

}
